home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Internet Info 1994 March
/
Internet Info CD-ROM (Walnut Creek) (March 1994).iso
/
networking
/
ip
/
ka9q
/
bmsrc.arc
/
MAIN.C
< prev
next >
Wrap
C/C++ Source or Header
|
1988-10-15
|
18KB
|
792 lines
/*
* Simple mail user interface for KA9Q IP/TCP package.
* A.D. Barksdale Garbee II, aka Bdale, N3EUA
* Copyright 1986 Bdale Garbee, All Rights Reserved.
* Permission granted for non-commercial copying and use, provided
* this notice is retained.
* Copyright 1987 1988 Dave Trulli NN2Z, All Rights Reserved.
* Permission granted for non-commercial copying and use, provided
* this notice is retained.
*
* revision history:
*
* v3.3 870467 D. Trulli nn2z
* v3.2 870314 D. Trulli nn2z
* v3.1 870117 D. Trulli nn2z
* Add multiple arguments mail commands.
* Send to multiple users.
* Add status commands;
* v3.0 871225 D. Trulli nn2z
* Heavily restructured program to use a index array of message.
* More compatible with UNIX type mail commands.
* v2.7 871214 D. Trulli nn2z
* Cleaned up header and message parsing to prevent lock up.
* Revised command structure.
* v2.6 870826 Bdale
* integrate PA0GRI's interface/gateway to the WA7MBL PBBS
* v2.5 870713 Bdale
* integrate additional patches from PA0GRI, minor cleanup
* v2.4 870614 - P. Karn
* "smart gateway" function moved to smtp client code in net.exe.
* User interface for sending mail reworked to resemble Berkeley Mail
* v2.3 870524
* Extensive addition/revision by Gerard PA0GRI. Now supports a healthy
* set of real commands.
* v2.1,2.2
* exact change history lost.
* v2.0 c.870115
* First version with command parser, only send and quit work.
* v1.0
* First attempt. Send messages only.
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include "bm.h"
extern char version[];
static char copyright1[] =
"Copyright 1987 Bdale Garbee, permission granted for non-commercial use.";
static char copyright2[] =
"Copyright 1988 Dave Trulli NN2Z, permission granted for non-commercial use.";
/* comands valid in bm.rc */
struct token rccmds[] = {
"smtp", SMTP,
"host", HOST,
"user", USER,
"edit", EDIT,
"fullname", NAME,
"reply", REPLY,
"maxlet", MAXLET,
"mbox", MBOX,
"record", RECORD,
"screen", SCREEN,
"folder", FOLDER,
"mqueue", MQUEUE,
NULLCHAR, 0
};
FILE *mfile = NULLFILE;
char *hostname = NULLCHAR; /* name of this host from rc file */
char *username = NULLCHAR; /* name of this user from rc file */
char *fullname = NULLCHAR; /* fullname of this user from rc file */
char *replyto = NULLCHAR; /* address for reply-to header */
char *maildir = NULLCHAR; /* defined mail directory */
char *mqueue = NULLCHAR; /* defined mqueue outbound directory */
char *savebox = NULLCHAR; /* name of the mbox text file */
char *record = NULLCHAR; /* record outbound mail in this file */
char *folder = NULLCHAR; /* directory for saveing read mail */
char *editor = NULLCHAR; /* user's favorite text editor */
char notename[9]; /* name of current notesfile */
char notefile[SLINELEN]; /* full pathname of mail text file */
char *mfilename = notefile; /* pointer to current mbox or mail file -f */
int current; /* the current message number */
int nmsgs; /* the number of messages in the notesfile */
int newmsgs; /* Number of new unread message */
int change; /* indicates that the mail file has been
* changed in this session */
int fflag = 0; /* true if current notesfile is not an mbox */
int qflag = 0; /* true if bm is used just to queue files */
unsigned maxlet = NLET+1; /* max number of messages in mailbox */
int tty = 0; /* tells if stdin is a tty */
struct let *mbox; /* pointer to the array of messages */
char usage[] = "Usage: bm [-u user] [-f file] \n or bm [-s subject] [-q] addr .. addr\n";
char badmsg[] = "Invalid Message number %d\n";
char nomail[] = "No messages\n";
char noaccess[] = "Unable to access %s\n";
main(argc,argv)
int argc;
char *argv[];
{
extern int optind;
extern char *optarg;
char *subjectline = NULLCHAR;
long tmp;
int c;
int ret;
#if defined(__TURBOC__) || defined(MICROSOFT)
(void) fclose(stdaux);
(void) fclose(stdprn);
#endif
loadconfig();
if (qflag == 0 && isatty(fileno(stdin))) {
/* announce ourselves */
screen_clear();
printf(" %s\n%s\n%s\n\n",version,copyright1,copyright2);
tty = 1;
}
current = 1;
nmsgs = 0;
/* check for important directories */
if(access(maildir,0)){
printf(noaccess,maildir);
exit(1);
}
if(access(mqueue,0)){
printf(noaccess,mqueue);
exit(1);
}
strncpy(notename,username,8);
notename[8] = '\0';
while ((c = getopt(argc,argv,"u:f:s:q")) != -1) {
switch(c) {
case 'f':
fflag++;
mfilename = optarg;
break;
case 'q':
qflag++;
break;
case 's':
subjectline = optarg;
break;
case 'u':
strncpy(notename,optarg,8);
notename[8] = '\0';
break;
case '?':
printf(usage);
exit(1);
}
}
/* set any signal handlers to catch break */
setsignals();
if(optind < argc){
dosmtpsend(NULLFILE,&argv[optind],argc-optind,subjectline);
(void) exit(0);
}
tmp = (long)maxlet * (long)sizeof(struct let);
#ifdef MSDOS
/*
* Since we are in the dos small model make sure that we
* don't overflow a unsigned short on the number bytes
* need for mallloc. If not checked malloc will
* succeed and we will be trashing ourself in no time.
*/
if ((tmp & 0xffff0000) ||
(mbox=(struct let *)malloc((unsigned short)tmp)) == (struct let *)NULL){
#else
if ((mbox=(struct let *)malloc((unsigned)tmp)) == (struct let *)NULL){
#endif
fprintf(stderr,
"Can't allocate memory table for %d messages\n",
maxlet);
(void) exit(1);
}
sprintf(notefile,"%s/%s.txt",maildir,notename);
if (!fflag && lockit())
exit(1);
ret = initnotes();
if (!fflag)
rmlock(maildir,notename);
if (ret != 0)
exit(1);
listnotes();
getcommand();
return 0;
}
loadconfig()
{
FILE *rcfp; /* handle for the configuration file */
char rcline[LINELEN]; /* buffer for config file reading */
register char *s,*p;
int line = 0;
char runcom[LINELEN];
char *getenv();
#ifdef UNIX
/* Try $HOME/RUNCOM */
if ((p = getenv("HOME")) != NULLCHAR)
sprintf(runcom, "%s/%s", p, RUNCOM);
#else
/* check for BMRC in the ENV */
if ((p = getenv("BMRC")) != NULLCHAR)
strcpy(runcom,p);
#endif
else
strcpy(runcom,RUNCOM);
if ((rcfp = fopen(runcom,"r")) == NULLFILE) { /* open config file */
printf("Cannot open '%s', check your installation\n",runcom);
(void) exit(1);
}
while (!feof(rcfp)) {
if (fgets(rcline,LINELEN,rcfp) == NULLCHAR)
break;
line++;
rip(rcline);
if (*rcline == '\0' || *rcline == ';'|| *rcline == '#')
continue;
/* find the argument to the command */
s = rcline;
/* skip the white space */
while(*s == ' ' || *s == '\t')
s++;
p = s;
/* skip the command */
while(*p && *p != ' ' && *p != '\t')
p++;
/* skip the white space */
while(*p == ' ' || *p == '\t')
p++;
if (*s == '\0')
continue;
switch (rc_line_type(s)) {
case HOST:
hostname = savestr(p);
break;
case USER:
username = savestr(p);
break;
case REPLY:
replyto = savestr(p);
break;
case EDIT:
editor = savestr(p);
break;
case SMTP:
maildir = savestr(p);
break;
case NAME:
fullname = savestr(p);
break;
case MAXLET:
maxlet = atoi(p)+1;
break;
case MBOX:
savebox = savestr(p);
break;
case RECORD:
record = savestr(p);
break;
case SCREEN:
#if defined(__TURBOC__)
setvideo(p);
#endif
break;
case FOLDER:
folder = savestr(p);
break;
case MQUEUE:
mqueue = savestr(p);
break;
default:
fprintf(stderr,
"%s: line %d Invalid command: '%s'\n",
runcom,line,rcline);
exit(1);
}
}
(void) fclose(rcfp);
if(maildir == NULLCHAR)
maildir = mailspool;
if(mqueue == NULLCHAR)
mqueue = mailqdir;
if(savebox == NULLCHAR)
savebox = "mbox";
if(hostname == NULLCHAR) {
fprintf(stderr,"%s: hostname not set\n",runcom);
exit(1);
}
if(username == NULLCHAR) {
fprintf(stderr,"%s: username not set\n",runcom);
exit(1);
}
}
/* return the line_type from a line of the configuration file */
rc_line_type(s)
register char *s;
{
register struct token *tp;
for (tp = rccmds; tp->str != NULLCHAR; tp++) {
if (strncmp(tp->str,s,strlen(tp->str)) == 0)
return tp->type;
}
return (NONE);
}
/* replace terminating end of line marker(s) with null */
rip(s)
register char *s;
{
for (; *s; s++)
if (*s == '\r' || *s == '\n') {
*s = '\0';
break;
}
}
/* copy a string return a pointer to it */
char *
savestr(s)
char *s;
{
register char *p;
p = malloc(strlen(s)+1);
if (p == NULLCHAR)
printf("No more memory\n");
else
strcpy(p,s);
return p;
}
dohelp()
{
screen_clear();
printf("\n\n");
printf(" d [msglist] delete a message\n");
printf(" m userlist mail a message\n");
printf(" s [msglist] [file] save message in file (default mbox)\n");
printf(" w [msglist] file save message in file no header\n");
printf(" f [msg] forward message\n");
printf(" b [msg] bounce message (remail)\n");
printf(" r [msg] reply to a message\n");
printf(" u [msglst] undelete a message\n");
printf(" p [msglst] print message on printer (DOS only)\n");
printf(" . display current message\n");
printf(" h display message headers in notefile\n");
printf(" l list unsent messages\n");
printf(" k kill unsent messages\n");
printf(" n [file] display or change notesfile\n");
printf(" # where # is the number of message to read\n");
printf(" x quit without changing mail file\n");
printf(" q quit\n");
printf(" ! cmd run dos command\n");
printf(" $ sync the notefile\n");
printf(" ? print this help screen\n");
}
/* save a message list in a file in mailbox format */
savemsg(argc,argv)
int argc;
register char *argv[];
{
register char *savefile;
int msgnum;
int i;
FILE *tfile;
char buf[LINELEN];
if (mfile == NULLFILE){
printf(nomail);
return;
}
if (argc == 0 || isdigit(*argv[argc - 1])) {
savefile = savebox;
} else {
savefile = argv[argc - 1];
--argc;
/* if it is just a file name and not a path name then check
** for a folder path defined and use that path to
** save the file.
*/
if (strpbrk(savefile,"/\\") == NULLCHAR && folder != NULLCHAR) {
sprintf(buf,"%s/%s",folder,savefile);
savefile = buf;
}
}
if ((tfile = fopen(savefile,"a")) == NULLFILE) {
perror(savefile);
return;
}
if (argc == 0)
msgtofile(current, tfile, 0);
else {
for (i = 0; i < argc; i++) {
msgnum = atoi(argv[i]);
if (msgnum >= 1 && msgnum <= nmsgs)
msgtofile(msgnum, tfile, 0);
else
printf(badmsg,msgnum);
}
}
(void) fclose(tfile);
printf("%s appended\n",savefile);
}
#ifdef MSDOS
/* send messages to the print device */
printmsg(argc,argv)
int argc;
char *argv[];
{
FILE *prn;
int msgnum;
int i;
if (mfile == NULLFILE){
printf(nomail);
return;
}
if ((prn = fopen("PRN","a")) == NULL) {
perror("PRN");
return;
}
if (argc == 0)
msgtofile(current, prn, 0);
else {
for (i = 0; i < argc; i++) {
msgnum = atoi(argv[i]);
if (msgnum >= 1 && msgnum <= nmsgs)
msgtofile(msgnum, prn, 0);
else
printf(badmsg,msgnum);
}
}
fclose(prn);
}
#endif
writemsg(argc,argv)
int argc;
char *argv[];
{
char *writefile;
int msgnum;
int i;
FILE *tfile;
if (mfile == NULLFILE){
printf(nomail);
return;
}
if (argc == 0 || isdigit(*argv[argc - 1])) {
printf("no file specified\n");
return;
} else {
writefile = argv[argc - 1];
--argc;
}
if ((tfile = fopen(writefile,"a")) == NULLFILE) {
perror(writefile);
return;
}
if (argc == 0)
msgtofile(current, tfile, 1);
else {
for (i = 0; i < argc; i++) {
msgnum = atoi(argv[i]);
if (msgnum >= 1 && msgnum <= nmsgs)
msgtofile(msgnum, tfile, 1);
else
printf(badmsg,msgnum);
}
}
(void) fclose(tfile);
printf("%s appended\n",writefile);
}
bmexit(x)
int x;
{
if(!fflag && lockit())
exit(1);
(void) closenotes();
if (!fflag)
rmlock(maildir,notename);
exit(x);
}
/* this is the main command processing loop */
getcommand()
{
FILE *tfile, *tmpfile();
char command[LINELEN]; /* command line */
char *args[MAXARGS];
int nargs;
char *cp;
register int msgnum;
register int i;
int ret;
printf("\nType ? for help.\n");
/* command parsing loop */
while(1) {
printf("\"%s\"> ",notename);
gets(command);
if (feof(stdin)) /* someone hit ^Z! */
strcpy(command,"q"); /* treat it like 'q' */
if(*command == '!') {
if (system(&command[1]))
perror("system");
continue;
}
if (*command) {
cp = command;
while (*cp && *cp != ' ')
cp++;
nargs = parse(cp,args,MAXARGS);
}
switch (*command) {
case 'm': /* send msg */
if (nargs == 0) {
printf("To: ");
gets(command);
nargs = parse(command,args,MAXARGS);
}
dosmtpsend(NULLFILE,args,nargs,NULLCHAR);
break;
case 's': /* save current msg to file */
savemsg(nargs,args);
break;
case 'w': /* write current msg to file */
writemsg(nargs,args);
break;
case 'x': /* abort */
(void) fclose(mfile);
(void) exit(0);
/* NOTREACHED */
break;
case 'p': /* print message */
#ifdef MSDOS
printmsg(nargs,args);
#else
printf("Command not available in this version\n");
#endif
break;
case 'r': /* reply */
if (nargs == 0)
msgnum = current;
else
msgnum = atoi(args[0]);
if (msgnum >= 1 && msgnum <= nmsgs)
reply(msgnum);
else
printf(badmsg,msgnum);
break;
case 'f':
if(nargs == 0)
msgnum = current;
else
msgnum = atoi(args[0]);
if (msgnum < 1 || msgnum > nmsgs) {
printf(badmsg,msgnum);
break;
}
if((tfile = tmpfile()) == NULLFILE)
printf("\nCannot open temp file\n");
else {
msgtofile(msgnum,tfile,0);
fseek(tfile,0L,0);
printf("To: ");
gets(command);
nargs = parse(command,args,MAXARGS);
dosmtpsend(tfile,args,nargs,NULLCHAR);
(void) fclose(tfile);
}
break;
case 'b': /* bounce a message */
if(nargs == 0)
msgnum = current;
else
msgnum = atoi(args[0]);
if (msgnum < 1 || msgnum > nmsgs) {
printf(badmsg,msgnum);
break;
}
if((tfile = tmpfile()) == NULLFILE)
printf("\nCannot open temp file\n");
else {
msgtofile(msgnum,tfile,0);
fseek(tfile,0L,0);
printf("To: ");
gets(command);
nargs = parse(command,args,MAXARGS);
bouncemsg(tfile,args,nargs);
(void) fclose(tfile);
}
break;
case 'u':
if (nargs == 0)
mbox[current].status &= ~DELETE;
else
for (i = 0; i < nargs; i++) {
msgnum = atoi(args[i]);
if( msgnum >= 1 && msgnum <= nmsgs)
mbox[msgnum].status &= ~DELETE;
else
printf(badmsg,msgnum);
}
break;
case 'l': /* display unsent messages */
listqueue();
break;
case 'k':
if (nargs == 0)
printf("No job id specified\n");
else
for (i = 0; i < nargs; i++)
killjob(args[i]);
break;
case 'n': /* display or change notefiles */
mboxnames(nargs,args);
break;
case 'q': /* quit */
if (isnewmail()) {
printf("New mail has arrived\n");
reinit();
} else
bmexit(0);
/* NOTREACHED */
break;
case '$':
reinit();
break;
case 'd': /* delete a message */
if (nargs == 0)
delmsg(current);
else
for ( i = 0; i < nargs; i++) {
msgnum = atoi(args[i]);
if( msgnum >= 1 && msgnum <= nmsgs)
delmsg(msgnum);
else
printf(badmsg,msgnum);
}
break;
case 'h': /* list message headers in notesfile */
listnotes();
break;
case '\0': /* a blank line prints next message */
printnext();
break;
case '?': /* help */
dohelp();
break;
case '.':
displaymsg(current);
break;
default:
if (!isdigit(*command))
printf("Invalid command - ? for help\n");
else {
msgnum = atoi(command);
if (msgnum < 0 || msgnum > nmsgs)
printf(badmsg,msgnum);
else {
current = msgnum;
displaymsg(current);
}
}
break;
}
}
}
/* list or change mbox */
mboxnames(argc,argv)
int argc;
char *argv[];
{
register char *cp;
int ret;
char line[80];
char buf[LINELEN];
if(argc != 0) {
if(!fflag && lockit())
return;
ret = closenotes();
if (!fflag)
rmlock(maildir,notename);
if (ret != 0)
exit(1);
if (strpbrk(argv[0],"/\\") != NULLCHAR) {
fflag = 1;
mfilename = argv[0];
} else {
fflag = 0;
mfilename = notefile;
strncpy(notename,argv[0],8);
notename[8] = '\0';
sprintf(notefile,"%s/%s.txt",maildir,notename);
}
if (!fflag && lockit()) {
mfile = NULLFILE;
printf("Mail file is busy\n");
return;
}
ret = initnotes();
if (!fflag)
rmlock(maildir,notename);
if (ret != 0)
exit(1);
listnotes();
} else { /* he wants to see what notefiles there are */
sprintf(buf,"%s/*.txt",maildir,notename);
filedir(buf,0,line);
while(line[0] != '\0') {
cp = strchr(line,'.');
*cp = '\0';
printf("notesfile -> %s\n",line);
filedir(buf,1,line);
}
}
}
reinit()
{
int ret;
if (!fflag && lockit())
return;
ret = closenotes();
if (!fflag)
rmlock(maildir,notename);
if (ret != 0)
exit(1);
if (!fflag && lockit()) {
mfile = NULLFILE;
printf("Mail file is busy\n");
return;
}
ret = initnotes();
if (!fflag)
rmlock(maildir,notename);
if (ret != 0)
exit(1);
listnotes();
}